//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
#ifndef __PINDRIVER_H_INCLUDED__
#define __PINDRIVER_H_INCLUDED__

#ifdef __cplusplus
extern "C" {
#endif

#define PIN_TIMEOUT         250

typedef struct _tagStreamDescriptorShadow
{
    PCS_STREAM_DESCRIPTOR pCsStreamDescriptorExternal;
    CS_STREAM_DESCRIPTOR  csStreamDescriptorShadow;
    BOOL                  m_fBusy;
} CS_STREAM_DESCRIPTOR_SHADOW, * PCS_STREAM_DESCRIPTOR_SHADOW;

typedef class CPinDevice 
{
public:
    CPinDevice( );

    ~CPinDevice( );

    bool
    InitializeSubDevice(
        PCAMERADEVICE pCamDevice
        );

    DWORD
    StreamInstantiate(
        PCSPROPERTY_STREAMEX_S pCsPropStreamEx,
        __out_bcount(OutBufLen) PUCHAR pOutBuf,
        DWORD                  OutBufLen,
        PDWORD                 pBytesTransferred
        );

    DWORD
    PinHandleConnectionRequests(
        PCSPROPERTY pCsProp,
        __out_bcount(OutBufLen) PUCHAR pOutBuf,
        DWORD  OutBufLen,
        PDWORD pBytesTransferred
        );

    DWORD
    PinHandleBufferRequest(
        DWORD  dwCommand,
        __out_bcount(OutBufLen) PUCHAR pOutBuf,
        DWORD  OutBufLen
        );

    DWORD
    HandlePinIO( PVOID PDDContext);

    void
    FlushBufferQueue();

    void
    SetState(
        CSSTATE   CsState,
        CSSTATE * CsPrevState
        );

    static
    DWORD IRQCallback( LPVOID dwContext, LPVOID pPDDContext );

    DWORD
    PauseStream( );

    bool
    CloseSubDevice( );

    ULONG
    PictureNumber( ) const;

    ULONG
    FramesDropped( ) const;

    ULONG
    FrameSize( ) const;

private:

    DWORD
    AllocateBuffer( 
        LPVOID pOutBuf
        );

    DWORD
    DeallocateBuffer(
        LPVOID pOutBuf
        );

    DWORD
    EnqueueDescriptor(
        LPVOID pOutBuf
        );

    bool
    RemoveBufferFromList(
        PCS_STREAM_DESCRIPTOR * ppCsStreamDesc,
        PVOID                 * ppMappedData,
        PVOID                 * ppUnmappedData
        );

    bool
    ResetBufferList( );
    
    DWORD
    PinHandleConnStateSubReqs(
        ULONG  ulReqFlags,
        __out_bcount(OutBufLen) PUCHAR pOutBuf,
        DWORD  OutBufLen,
        PDWORD pBytesTransferred
        );

    DWORD
    PinHandleConnDataFormatSubReqs(
        ULONG                          ulReqFlags,
        PCS_DATAFORMAT_VIDEOINFOHEADER pCsDataFormatVidInfoHdr,
        PDWORD                         pBytesTransferred
        );

    BOOL InitMsgQueueDescriptor(
        PCS_MSGQUEUE_BUFFER pCsMsgQBuff, 
        PCS_STREAM_DESCRIPTOR pCsStreamDesc, 
        PVOID pMappedData, 
        PVOID pUnmappedData, 
        BOOL bFillBuffer,
        PVOID pPDDContext);

    DWORD
    GetIndexFromHandle( 
        DWORD  Handle,
        LPVOID pBuffer
        );

    DWORD 
    CreateHandle( 
        DWORD  Index, 
        LPVOID pBuffer 
        );

    DWORD
    SwSetupStreamDescriptor(
        DWORD                 Index,
        PCS_STREAM_DESCRIPTOR pCsStreamDesc,
        LPVOID                pBuffer
        );

    DWORD
    HwSetupStreamDescriptor(
        DWORD Index
        );

    CSPROPERTY_BUFFER_MODE 
        GetCurrentMemoryModel(
        );

    ULONG              m_PinId;
    ULONG              m_MaxNumOfBuffers;
    ULONG              m_FrameSize;
    ULONG              m_FramesDropped;
    ULONG              m_PictureNumber;

    PCAMERADEVICE      m_pCamAdapter;
    CS_DATARANGE_VIDEO m_CsDataRangeVideo;

    DWORD              m_BufferCount;
    PCS_STREAM_DESCRIPTOR_SHADOW m_pStreamDescriptorList;

    REFERENCE_TIME     m_RtAveTimePerFrame;
    DWORD              m_msStart;
    DWORD              m_msLastPT;

    HANDLE             m_hMsgQ;

    CRITICAL_SECTION   m_csStreamBuffer;
    CRITICAL_SECTION  *m_pcsDeviceState;

    CSSTATE            m_CsState;

    bool               m_fDiscontinuity;

    CSPROPERTY_BUFFER_MODE 
                       m_MemoryModel;

} PINDEVICE, * PPINDEVICE;

typedef struct CPinInitHandle
{
    PCAMERADEVICE pCamDevice;
} PININITHANDLE, * PPININITHANDLE;

#ifdef __cplusplus
}
#endif

#endif //__PINDRIVER_H_INCLUDED__
